home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickTime / Programming Stuff / Sample Code / Image Compression Mgr / PictMovier / pictmovier.c < prev    next >
Encoding:
Text File  |  1994-12-11  |  37.2 KB  |  1,791 lines  |  [TEXT/MPS ]

  1. /*
  2.   File:        PictMovier.c
  3.   Contains:    Application to make a movie from PICTs with various processes
  4.   Written by:    Mark Krueger
  5.   Copyright:    © 1990-1994 by Apple Computer, Inc., all rights reserved.
  6.   Change History (most recent first):
  7.   12/06/94            khs        Fixes for MW
  8.   06/05/94            PM/MHK    New Today    
  9.         
  10.   This example shows how you can make movies by doing processing on pictures.
  11.   This allows a process that takes a long time to be shown at much faster rates
  12.   as a QuickTime movie. Any type of processing can be done, such as filtering, 
  13.   transitions, 3-D transformations. This example shows two trivial examples.
  14.   The first simple does a linear cross fade between two images. The second creates
  15.   a random dot stereogram ( an image that if you stare at it long enough you can
  16.   see three dimensional depth in ( without special glasses ). This works from a single
  17.   image and shows how the effect can be varied from frame to frame.
  18.   Note that the code is not necessarily well commented, but should prove useful as 
  19.   a jumping off point for making your own movie creation applications.
  20. */
  21.  
  22.  
  23. // INCLUDES
  24. #include    <Types.h>
  25. #include    <Files.h>
  26. #include    <Quickdraw.h>
  27. #include    <Packages.h>
  28. #include    <Memory.h>
  29. #include    <Fonts.h>
  30. #include    <Events.h>
  31. #include    <OSUtils.h>
  32. #include    <ToolUtils.h>
  33. #include    <Menus.h>
  34. #include    <Dialogs.h>
  35. #include    <stdio.h>
  36. #include    <Errors.h>
  37. #include    <Scrap.h>
  38. #include    <Desk.h>
  39. #include    <string.h>
  40. #include    <GestaltEqu.h>
  41. #include    <Resources.h>
  42. #include    <Finder.h>
  43. #include    <PictUtil.h>
  44. #include    <palettes.h>
  45. #include    <OSEvents.h>
  46. #include    <Math.h>
  47. #include    <SegLoad.h>
  48. #include    <Windows.h>
  49.  
  50.  
  51. #ifndef    THINK_C
  52. #include    <Strings.h>
  53. #endif
  54.  
  55. #include    <ImageCompression.h>
  56. #include     <QuickTimeComponents.h>
  57. #include    <Components.h>
  58. #include    <Movies.h>
  59.  
  60.  
  61. // DEFINES
  62. #define kNumberSteps  30
  63. #define kFrameRate 10            /* frames per second */
  64. #define    kCodecID  anyCodec
  65. #define    kCodecType  (CodecType) 'rpza'
  66. #define    kCodecDepth 32
  67. #define    kCodecQuality  codecNormalQuality
  68.  
  69.  
  70. // FUNCTION PROTOTYPES
  71. void FixMenus(void);
  72. void SetupMenus(void);
  73. void Error(char* msg, OSErr code);
  74. void ShowAboutBox(void);
  75. void Initialize(void);
  76. long DoClose(WindowPtr wind);
  77. void SetCompression(void);
  78. void SetStages(void);
  79. void DoHLock(Handle h);
  80. void DoHUnlock(Handle h);
  81. void DoDisposHandle(Handle h);
  82. void DoPreview(void);
  83. void DoMovie(void);
  84. void DoCopy(void);
  85. void DoCut(void);
  86. void DoPaste(void);
  87. void DoClear(void);
  88. void DoUndo(void);
  89. Boolean HandleEvents(EventRecord* myEvent);
  90. OSErr DoOpen(FSSpec* fsp);
  91. long BetterRand(long reseed);
  92. unsigned char DecodeDepth(unsigned char pix);
  93. void DoCrossFade(long stageNum,
  94.                  long totalStages,
  95.                  Boolean reverse);
  96. void DoRandomDotStereogram(long stageNum,
  97.                            long totalStages,
  98.                            Boolean reverse);
  99. void DoStage(long stageNum,
  100.              long totalStages,
  101.              Boolean reverse);
  102. void DoClear();
  103. void DoUpdate(CWindowPtr wind);
  104. short DoCommand(long mResult);
  105. OSErr AllocateBuffers(void);
  106. CWindowPtr MakeSWindow(Rect* frame,
  107.                        StringPtr name,
  108.                        GWorldPtr buffer);
  109.  
  110.  
  111. // GLOBALS
  112. CWindowPtr gSrcWindow = nil;
  113. CWindowPtr gAltWindow = nil;
  114. CWindowPtr gDstWindow = nil;
  115. Rect gOriginalPicFrame;
  116. Boolean gZoomed = false;
  117. Boolean gFitToWindow = true;
  118. Boolean gHasNewStdFile = false;
  119. PicHandle gOriginalPicture = nil;
  120. Boolean gCompressed = false;
  121. GWorldPtr gWorld = nil;
  122. GWorldPtr gAltWorld = nil;
  123. GWorldPtr gDstWorld = nil;
  124. GWorldPtr gBufferWorld = nil;
  125. long gFrameNumber = -1;
  126. MenuHandle gMenus[4];                            // our menus
  127. Boolean gExitFlag = false;
  128. WindowPtr gActiveWindow = nil;
  129. Rect gRect;
  130.  
  131. short gStripWidth = 128;
  132. short gDepthFactor = 16;
  133. Boolean gDepthDecodeTabInted = false;
  134.  
  135. CodecType gCodecType = kCodecType;
  136. CodecQ gCodecQuality = kCodecQuality;
  137. CodecQ gCodecTemporalQuality = 0;
  138. short gCodecDepth = kCodecDepth;
  139. long gFrameRate = kFrameRate;
  140. long gKeyFrameRate = kFrameRate;
  141. CodecComponent gCodecID = kCodecID;
  142.  
  143. long gNumberSteps = kNumberSteps;
  144.  
  145.  
  146.  
  147. Boolean gOversample = false;
  148.  
  149. Boolean gBackwards = false;
  150.  
  151. #define        APPLE_MENU    0
  152. #define        APPLE_MENU_ID    128
  153.  
  154. #define        FILE_MENU    1
  155. #define        FILE_MENU_ID    129
  156.  
  157. #define        FILE_M_OPEN    1
  158. #define        FILE_M_CLOSE 2
  159. #define        FILE_M_SAVE    3
  160. #define        FILE_M_QUIT    5
  161.  
  162.  
  163. #define        EDIT_MENU    2
  164. #define        EDIT_MENU_ID    130
  165. #define        EDIT_M_UNDO        1
  166. #define        EDIT_M_CUT        3
  167. #define        EDIT_M_COPY        4
  168. #define        EDIT_M_PASTE    5
  169. #define        EDIT_M_CLEAR    6
  170.  
  171. #define        MOVIE_MENU    3
  172. #define        MOVIE_MENU_ID    131
  173.  
  174. #define        MOVIE_M_COMPRESS    1
  175. #define        MOVIE_M_STAGES        2
  176. #define        MOVIE_M_OVERSAMPLE    3
  177. #define        MOVIE_M_BACKWARDS    4
  178. #define        MOVIE_M_PREVIEW        6
  179. #define        MOVIE_M_MOVIE        8
  180.  
  181.  
  182. Boolean gDoCrossFade = true;                    // type of processing to do ( set for crossfade, set to false to do random dot stereograms )
  183.  
  184.  
  185. Boolean gRequiresAlternate = true;                // if true means requires second picture for processing
  186.  
  187.  
  188. short gDepth = 32;                                // pixel depth of allocated image buffers
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195. /*********************************************
  196.   Funtion prototypes.
  197. */
  198.  
  199.  
  200.  
  201. /*********************************************
  202.   Clean up menu hiliting
  203. *********************************************/
  204.  
  205. void FixMenus(void)
  206. {
  207.     Boolean gotAllWindows = gSrcWindow != nil && (!gRequiresAlternate || gAltWindow != nil);
  208.     Boolean gotAnyWindows = gSrcWindow != nil || gAltWindow != nil;
  209.  
  210.     DisableItem(gMenus[FILE_MENU], FILE_M_SAVE);
  211.     if (gotAnyWindows)
  212.         EnableItem(gMenus[FILE_MENU], FILE_M_CLOSE);
  213.     else
  214.         DisableItem(gMenus[FILE_MENU], FILE_M_CLOSE);
  215.  
  216.     if (gotAllWindows)
  217.         DisableItem(gMenus[FILE_MENU], FILE_M_OPEN);
  218.     else
  219.         EnableItem(gMenus[FILE_MENU], FILE_M_OPEN);
  220.  
  221.     if (!gotAllWindows)
  222.     {
  223.         DisableItem(gMenus[MOVIE_MENU], MOVIE_M_MOVIE);
  224.         DisableItem(gMenus[MOVIE_MENU], MOVIE_M_PREVIEW);
  225.         DisableItem(gMenus[MOVIE_MENU], MOVIE_M_OVERSAMPLE);
  226.     }
  227.     else
  228.     {
  229.         EnableItem(gMenus[MOVIE_MENU], MOVIE_M_MOVIE);
  230.         EnableItem(gMenus[MOVIE_MENU], MOVIE_M_PREVIEW);
  231.         EnableItem(gMenus[MOVIE_MENU], MOVIE_M_OVERSAMPLE);
  232.     }
  233.  
  234.     DisableItem(gMenus[EDIT_MENU], EDIT_M_CUT);
  235.     DisableItem(gMenus[EDIT_MENU], EDIT_M_COPY);
  236.     DisableItem(gMenus[EDIT_MENU], EDIT_M_PASTE);
  237.  
  238.     DisableItem(gMenus[EDIT_MENU], EDIT_M_CLEAR);
  239.     DisableItem(gMenus[EDIT_MENU], EDIT_M_UNDO);
  240.     CheckItem(gMenus[MOVIE_MENU], MOVIE_M_OVERSAMPLE, gOversample);
  241.     CheckItem(gMenus[MOVIE_MENU], MOVIE_M_BACKWARDS, gBackwards);
  242. }
  243.  
  244.  
  245. /*********************************************
  246.   Initialize menu bar.
  247. *********************************************/
  248.  
  249. void SetupMenus(void)
  250. {
  251.  
  252.     gMenus[APPLE_MENU] = GetMenu(APPLE_MENU_ID);
  253.     AddResMenu(gMenus[APPLE_MENU], (ResType)'DRVR');
  254.     InsertMenu(gMenus[APPLE_MENU], 0);
  255.     gMenus[FILE_MENU] = GetMenu(FILE_MENU_ID);
  256.     InsertMenu(gMenus[FILE_MENU], 0);
  257.     gMenus[EDIT_MENU] = GetMenu(EDIT_MENU_ID);
  258.     InsertMenu(gMenus[EDIT_MENU], 0);
  259.     gMenus[MOVIE_MENU] = GetMenu(MOVIE_MENU_ID);
  260.     InsertMenu(gMenus[MOVIE_MENU], 0);
  261.     DrawMenuBar();
  262.     FixMenus();
  263. }
  264.  
  265.  
  266. /*********************************************
  267.   Prepare for work.
  268. *********************************************/
  269.  
  270.  
  271. void Initialize(void)
  272. {
  273.     Ptr size;
  274.     long resp;
  275.  
  276.     size = GetApplLimit();
  277.     SetApplLimit(size - 32 * 1024);                /* make room on stack so Quickdraw can do big pictures */
  278.     MaxApplZone();
  279.  
  280.     /*    initialize managers */
  281.  
  282.     InitGraf(&qd.thePort);
  283.     InitFonts();
  284.     InitWindows();
  285.     InitMenus();
  286.     InitDialogs(nil);
  287.     InitCursor();
  288.     FlushEvents(everyEvent, 0);
  289.     SetupMenus();
  290.     CouldAlert(140);
  291.  
  292.     if (NGetTrapAddress(0xab1d, ToolTrap) == NGetTrapAddress(0x9f, ToolTrap))
  293.     {
  294.         ExitToShell();
  295.     }
  296.     if (Gestalt(gestaltQuickTime, &resp) != 0)
  297.     {
  298.         ExitToShell();
  299.     }
  300.  
  301. }
  302.  
  303.  
  304. /*********************************************
  305.   If some kind of fatal error happened come here.
  306. *********************************************/
  307.  
  308. void Error(char* msg,
  309.            OSErr code)
  310. {
  311.     char buf[256];
  312.  
  313.     GWorldPtr saveWorld;
  314.     GDHandle saveGD;
  315.     CGrafPtr wmgrPort;
  316.  
  317.     GetGWorld(&saveWorld, &saveGD);
  318.     GetCWMgrPort(&wmgrPort);
  319.     SetGWorld(wmgrPort, nil);
  320.     if (code)
  321.     {
  322.         sprintf(buf, "%s %d", msg, code);
  323.         msg = buf;
  324.     }
  325.     c2pstr(msg);
  326.     ParamText((StringPtr)msg, "\p", 0, 0);
  327.     if (code == 0)
  328.         Alert(140, nil);
  329.     else
  330.         StopAlert(140, nil);
  331.     SetGWorld(saveWorld, saveGD);
  332. }
  333.  
  334.  
  335. void ShowAboutBox(void)
  336. {
  337.  
  338.     ParamText("\pPictMovier", "\pQuickTime!", 0, 0);
  339.     Alert(140, nil);
  340. }
  341.  
  342.  
  343. /*
  344.   Close a window
  345. */
  346.  
  347.  
  348. long DoClose(WindowPtr wind)
  349. {
  350.  
  351.     if (wind == nil)
  352.         return (0);
  353.     if (gActiveWindow == wind)
  354.         gActiveWindow = nil;
  355.  
  356.     if (wind == (WindowPtr)gSrcWindow)
  357.     {
  358.         DoClear();
  359.         gSrcWindow = nil;
  360.         DisposeGWorld(gWorld);
  361.         gWorld = nil;
  362.     }
  363.     else if (wind == (WindowPtr)gAltWindow)
  364.     {
  365.         DoClear();
  366.         gAltWindow = nil;
  367.         DisposeGWorld(gAltWorld);
  368.         gAltWorld = nil;
  369.     }
  370.     else if (wind == (WindowPtr)gDstWindow)
  371.     {
  372.         gDstWindow = nil;
  373.     }
  374.     CloseWindow(wind);
  375.     return (0);
  376.  
  377. }
  378.  
  379.  
  380.  
  381. /*********************************************
  382.   Allow the user to set the compression parameters with the standard compression dialog.
  383. *********************************************/
  384.  
  385. void SetCompression(void)
  386. {
  387.     ComponentInstance ci;
  388.     Point where;
  389.     SCParams p;
  390.  
  391.  
  392.     where.h = where.v = -2;
  393.     ci = OpenDefaultComponent('scdi', 0);
  394.     if (ci == nil)
  395.     {
  396.         Error("Couldn't open StdCompression", 0);
  397.         return;
  398.     }
  399.  
  400.     p.flags = scShowMotionSettings;
  401.     p.theCodecType = gCodecType;
  402.     p.theCodec = gCodecID;
  403.     p.spatialQuality = gCodecQuality;
  404.     p.temporalQuality = gCodecTemporalQuality;
  405.     p.depth = gCodecDepth;
  406.     p.frameRate = gFrameRate << 16;
  407.     p.keyFrameRate = gKeyFrameRate;
  408.  
  409.     SCGetCompressionExtended(ci, &p, where, 0,0,0,0);
  410.  
  411.     gCodecType = p.theCodecType;
  412.     gCodecQuality = p.spatialQuality;
  413.     gCodecTemporalQuality = p.temporalQuality;
  414.     gCodecDepth = p.depth;
  415.     gFrameRate = p.frameRate >> 16;
  416.     gKeyFrameRate = p.keyFrameRate;
  417.     gCodecID = p.theCodec;
  418. }
  419.  
  420.  
  421. /*
  422.   Allow the user to set the number of stages she wants the processing to take.
  423. */
  424.  
  425. void SetStages(void)
  426. {
  427.  
  428.  
  429. #define    STAGE_DLOG    128
  430. #define    IT_STAGES    3
  431. #define    IT_LINEAR    4
  432. #define    IT_OK    1
  433. #define    IT_CANCEL    2
  434.  
  435.     CGrafPtr savePort;
  436.     DialogPtr theDialog;
  437.     short itemType;
  438.     Handle itemHdl;
  439.     Rect itemRect;
  440.     short itemHit,
  441.      lastItem = -1;
  442.     Boolean done = false;
  443.     Point tp;
  444.     GDHandle saveGD;
  445.     Str255 text;
  446.     long num;
  447.     long stageCount = gNumberSteps;
  448.     Boolean linear = true;
  449.  
  450.     if ((theDialog = GetNewDialog(STAGE_DLOG, nil, (WindowPtr) - 1)) == nil)
  451.         return;
  452.  
  453.     GetMouse(&tp);
  454.     GetGWorld(&savePort, &saveGD);
  455.     SetPort(theDialog);
  456.     GetDItem(theDialog, IT_OK, &itemType, &itemHdl, &itemRect);
  457.     PenSize(3, 3);
  458.     InsetRect(&itemRect, -4, -4);
  459.     FrameRoundRect(&itemRect, 16, 16);
  460.  
  461.  
  462.     GetDItem(theDialog, IT_STAGES, &itemType, &itemHdl, &itemRect);
  463.  
  464.     sprintf((char*)text, "%ld", stageCount);
  465.     c2pstr((char*)text);
  466.     SetIText(itemHdl, text);
  467.  
  468.     SelIText(theDialog, IT_STAGES, 0, 32767);
  469.  
  470.     GetDItem(theDialog, IT_LINEAR, &itemType, &itemHdl, &itemRect);
  471.     SetCtlValue((ControlHandle)itemHdl, linear);
  472.     HiliteControl((ControlHandle)itemHdl, 255);
  473.  
  474.     while (!done)
  475.     {
  476.         ModalDialog(nil, &itemHit);
  477.         if (itemHit != lastItem)
  478.         {
  479.             switch (lastItem)
  480.             {
  481.                 case IT_STAGES:
  482.                     GetDItem(theDialog, IT_STAGES, &itemType, &itemHdl, &itemRect);
  483.                     GetIText(itemHdl, text);
  484.                     p2cstr(text);
  485.                     if (sscanf((char*)text, "%ld", &num) == 1 && num > 0)
  486.                         stageCount = num;
  487.                     else
  488.                         SysBeep(1);
  489.                     sprintf((char*)text, "%ld", stageCount);
  490.                     c2pstr((char*)text);
  491.                     SetIText(itemHdl, text);
  492.                     break;
  493.             }
  494.             lastItem = itemHit;
  495.         }
  496.         switch (itemHit)
  497.         {
  498.             case IT_OK:
  499.                 gNumberSteps = stageCount;
  500.                 done = true;
  501.                 break;
  502.             case IT_CANCEL:
  503.                 done = true;
  504.                 break;
  505.             case IT_LINEAR:
  506.                 linear =!linear;
  507.                 GetDItem(theDialog, IT_LINEAR, &itemType, &itemHdl, &itemRect);
  508.                 SetCtlValue((ControlHandle)itemHdl, linear);
  509.                 break;
  510.             default:
  511.                 break;
  512.         }
  513.     }
  514.     CloseDialog(theDialog);
  515.     SetGWorld(savePort, saveGD);
  516. }
  517.  
  518.  
  519. void DoStage(long stageNum,
  520.              long totalStages,
  521.              Boolean reverse)
  522. {
  523.  
  524.  
  525.     if (gDoCrossFade)
  526.         DoCrossFade(stageNum, totalStages, reverse);
  527.     else
  528.         DoRandomDotStereogram(stageNum, totalStages, reverse);
  529. }
  530.  
  531.  
  532.  
  533. /*********************************************
  534.   This processing routine creates a random dot stereogram of the input picture.
  535.   The second picture is not used.
  536. ********************************************/
  537.  
  538.  
  539.  
  540.  
  541.  
  542. void DoRandomDotStereogram(long stageNum,
  543.                            long totalStages,
  544.                            Boolean reverse)
  545. {
  546.  
  547.  
  548.     /* StdFile stuff */
  549.  
  550.     CGrafPtr savePort;
  551.     GDHandle saveGD;
  552.     char* ip,
  553.     * rp,
  554.     * pp,
  555.     * opp,
  556.     * qp;
  557.     char* sip,
  558.     * srp,
  559.     * spp;
  560.     short rowBytes;
  561.     short sRowBytes;
  562.     char mode = 1;
  563.  
  564.     /* for sepecifying compression */
  565.  
  566.     short i,
  567.      j,
  568.      x,
  569.      y,
  570.      height,
  571.      width;
  572.     unsigned char pix,
  573.      spix,
  574.      ppix,
  575.      qpix;
  576.  
  577.     char* lineBuf = nil;
  578.     char* newLineBuf = nil;
  579.     char* tLineBuf = nil;
  580. #ifdef RDS_NEW_SEED_EACH_FRAME 
  581.     unsigned long timeseed;
  582. #endif
  583.  
  584.     //#define    RDS_DEPTH_FACTOR_VARIES            // set this to increase depth as movie progresses
  585.  
  586.     //#define    RDS_STRIP_WIDTH_VARIES            // set this to increase repeat strip as movie progresses
  587.  
  588.     //#define    RDS_NEW_SEED_EACH_FRAME            // set this to have a new random background for each frame 
  589.  
  590.  
  591.  
  592. #ifdef    RDS_NEW_SEED_EACH_FRAME
  593.     GetDateTime(×eed);
  594.     BetterRand(time);
  595. #else
  596.     BetterRand(1);
  597. #endif
  598.  
  599. #ifdef    RDS_DEPTH_FACTOR_VARIES
  600.     gDepthFactor = 1 + (stageNum * 64) / totalStages;
  601.     gDepthDecodeTabInted = false;
  602. #else
  603.     gDepthFactor = 16;
  604. #endif
  605.  
  606. #ifdef    RDS_STRIP_WIDTH_VARIES
  607.     gStripWidth = 32 + (stageNum * 256) / totalStages;
  608.  
  609. #else
  610.     gStripWidth = 128;
  611. #endif
  612.  
  613.     GetGWorld(&savePort, &saveGD);
  614.     SetGWorld(gDstWorld, nil);
  615.     EraseRect(&gDstWorld->portRect);
  616.     width = gWorld->portRect.right - gWorld->portRect.left;
  617.     height = gWorld->portRect.bottom - gWorld->portRect.top;
  618.     LockPixels(gWorld->portPixMap);
  619.     sRowBytes = (*gWorld->portPixMap)->rowBytes & 0x7fff;
  620.     sip = GetPixBaseAddr(gWorld->portPixMap);
  621.     SetGWorld(gDstWorld, nil);
  622.  
  623.     LockPixels(gDstWorld->portPixMap);
  624.     rowBytes = (*gDstWorld->portPixMap)->rowBytes & 0x7fff;
  625.     ip = GetPixBaseAddr(gDstWorld->portPixMap);
  626.  
  627.  
  628.     lineBuf = NewPtr(sRowBytes);
  629.     if (lineBuf == nil)
  630.     {
  631.         Error("allocating line buffer", 0);
  632.         goto done;
  633.     }
  634.     newLineBuf = NewPtr(rowBytes);
  635.     if (newLineBuf == nil)
  636.     {
  637.         Error("allocating nline buffer", 0);
  638.         goto done;
  639.     }
  640.     tLineBuf = NewPtr(sRowBytes);
  641.     if (tLineBuf == nil)
  642.     {
  643.         Error("allocating tline buffer", 0);
  644.         goto done;
  645.     }
  646.     SwapMMUMode(&mode);
  647.     if (gDepth == 1)
  648.     {
  649.  
  650.         rp = ip;
  651.         for (y = 0; y < height; y++)
  652.         {
  653.             pp = rp;
  654.             for (x = 0; x < gStripWidth / 8; x++, pp++)
  655.             {
  656.                 pix = 0;
  657.                 for (i = 0; i < 8; i++)
  658.                 {
  659.                     pix <<= 1;
  660.                     if (BetterRand(0) % 5 == 0)
  661.                         pix |= 1;
  662.                 }
  663.                 qp = pp;
  664.                 for (j = 0; j < width / gStripWidth; j++)
  665.                 {
  666.                     *qp = pix;
  667.                     qp += gStripWidth / 8;
  668.                 }
  669.             }
  670.             rp += rowBytes;
  671.         }
  672.         rp = ip;
  673.         srp = sip;
  674.  
  675.  
  676.         for (y = 0; y < height; y++)
  677.         {
  678.             pp = rp;
  679.             spp = srp;
  680.             spp += gDepthFactor / 8;
  681.             qp = pp;
  682.             BlockMove(pp, tLineBuf, sRowBytes);
  683.             qp = tLineBuf;
  684.             pp = qp;
  685.             qp += gDepthFactor / 8;
  686.  
  687.             opp = newLineBuf;
  688.             for (x = 0; x < width / 8 - gStripWidth / 8; x++, pp++, qp++, opp++)
  689.             {
  690.                 spix = *spp++;
  691.                 qpix = *qp;
  692.                 ppix = *pp;
  693.                 pix = 0;
  694.                 for (i = 0; i < 8; i++)
  695.                 {
  696.                     pix <<= 1;
  697.                     if ((spix & 0x80))
  698.                         pix |= (qpix & 0x80) != 0 ? 1 : 0;
  699.                     else
  700.                         pix |= (ppix & 0x80) != 0 ? 1 : 0;
  701.                     spix <<= 1;
  702.                     ppix <<= 1;
  703.                     qpix <<= 1;
  704.                 }
  705.                 *opp = pix;
  706.                 *(pp + gStripWidth / 8) = pix;
  707.             }
  708.             BlockMove(newLineBuf, rp + gStripWidth / 8, rowBytes - gStripWidth / 8);
  709.             rp += rowBytes;
  710.             srp += sRowBytes;
  711.         }
  712.     }
  713.     else if (gDepth == 8 || gDepth == 40)
  714.     {
  715.  
  716.         rp = ip;
  717.  
  718.         for (y = 0; y < height; y++)
  719.         {
  720.             pp = rp;
  721.             for (x = 0; x < gStripWidth; x++)
  722.             {
  723.                 *pp++ = BetterRand(0);
  724.             }
  725.             rp += rowBytes;
  726.         }
  727.  
  728.         rp = ip;
  729.         srp = sip;
  730.  
  731.         for (y = 0; y < height; y++)
  732.         {
  733.             pp = rp;
  734.             spp = srp;
  735.             spp += gStripWidth;
  736.  
  737.             qp = pp;
  738.             BlockMove(pp, tLineBuf, sRowBytes);
  739.             qp = tLineBuf;
  740.             pp = qp;
  741.  
  742.             opp = newLineBuf;
  743.             for (x = 0; x < width - gStripWidth; x++, pp++, qp++, opp++)
  744.             {
  745.                 spix = *spp++;
  746.                 ppix = *pp;
  747.  
  748.                 pix = *(qp + DecodeDepth(spix));
  749.                 *opp = pix;
  750.                 *(pp + gStripWidth) = pix;
  751.             }
  752.             BlockMove(newLineBuf, rp + gStripWidth, rowBytes - gStripWidth);
  753.             rp += rowBytes;
  754.             srp += sRowBytes;
  755.         }
  756.     }
  757.     SwapMMUMode(&mode);
  758.     UnlockPixels(gDstWorld->portPixMap);
  759.  
  760.     SetGWorld(savePort, saveGD);
  761. done:if (newLineBuf)
  762.         DisposPtr(newLineBuf);
  763.     if (lineBuf)
  764.         DisposPtr(lineBuf);
  765.     if (tLineBuf)
  766.         DisposPtr(tLineBuf);
  767.  
  768.  
  769. }
  770.  
  771. /*********************************************
  772.   a better random function than the one in the ROM 
  773. *********************************************/
  774.  
  775. long BetterRand(long reseed)
  776. {
  777. #define    A    16807
  778. #define    M    2147483647
  779. #define    Q    127773
  780. #define    R    2836
  781.  
  782.     static long seed = 1;
  783.  
  784.     long lo,
  785.      hi,
  786.      test;
  787.  
  788.     if (reseed != 0)
  789.         seed = reseed;
  790.     hi = seed / Q;
  791.     lo = seed % Q;
  792.     test = A * lo - R * hi;
  793.     if (test > 0)
  794.         seed = test;
  795.     else
  796.         seed = test + M;
  797.     return (seed / (M >> 16));
  798. }
  799.  
  800.  
  801. unsigned char DecodeDepth(unsigned char pix)
  802.  
  803. {
  804.  
  805.     static unsigned char table[256];
  806.     short i;
  807.  
  808.     if (!gDepthDecodeTabInted)
  809.     {
  810.         gDepthDecodeTabInted = 1;
  811.         for (i = 0; i < 255; i++)
  812.         {
  813.             table[i] = (i * gDepthFactor) / 255;
  814.         }
  815.     }
  816.     return (table[pix]);
  817.  
  818. }
  819.  
  820.  
  821.  
  822. /*********************************************
  823.   This processing routine does a linear cross dissolve between the two images,
  824.   using CopyBits with blend mode. It shows how to do a process which involves 
  825.   both images. Any type of process could be done here, using the three parameters
  826.   to determine how much of the processing has progressed.
  827.   Note: See the Develop article by Konstantin Othmar ( sorry I forget the issue number )
  828.   about CopyBits to learn how to do other cool effects just using CopyBits.
  829. *********************************************/
  830.  
  831.  
  832.  
  833. void DoCrossFade(long stageNum,
  834.                  long totalStages,
  835.                  Boolean reverse)
  836. {
  837.     GWorldPtr saveWorld;
  838.     GDHandle saveGD;
  839.     RGBColor opColor;
  840.  
  841.  
  842.     if (reverse)
  843.         opColor.red = opColor.green = opColor.blue = (stageNum * 0xffff) / totalStages;
  844.     else
  845.         opColor.red = opColor.green = opColor.blue = ((totalStages - stageNum) * 0xffff) / totalStages;
  846.  
  847.     GetGWorld(&saveWorld, &saveGD);
  848.  
  849.     SetGWorld(gDstWorld, nil);
  850.     CopyBits((BitMap *) * gAltWorld->portPixMap, (BitMap *) * gDstWorld->portPixMap, &gAltWorld->portRect, &gDstWorld->portRect, ditherCopy, nil);
  851.     OpColor(&opColor);
  852.     CopyBits((BitMap *) * gWorld->portPixMap, (BitMap *) * gDstWorld->portPixMap, &gWorld->portRect, &gDstWorld->portRect, blend, nil);
  853.     SetGWorld(saveWorld, saveGD);
  854.  
  855. }
  856.  
  857.  
  858. /* 
  859.   The following three routines are here because the MPW 3.2 c compiler 
  860.   screw up compiling the DoMovie routine if you use the "straight" calls.
  861.   Try it and see and complain to DTS.
  862. */
  863.  
  864.  
  865. void DoHLock(Handle h)
  866. {
  867.     HLock(h);
  868. }
  869.  
  870.  
  871. void DoHUnlock(Handle h)
  872. {
  873.     HUnlock(h);
  874. }
  875.  
  876.  
  877. void DoDisposHandle(Handle h)
  878. {
  879.     DisposHandle(h);
  880. }
  881.  
  882. /*********************************************
  883.   Show a preview of some stage in the process.
  884. ********************************************/
  885.  
  886.  
  887. void DoPreview(void)
  888. {
  889.  
  890.  
  891. #define    PV_DLOG    129
  892. #define    IT_STAGE    4
  893. #define    IT_OK    1
  894. #define    IT_CANCEL    2
  895.  
  896.     CGrafPtr savePort;
  897.     DialogPtr theDialog;
  898.     short itemType;
  899.     Handle itemHdl;
  900.     Rect itemRect;
  901.     short itemHit,
  902.      lastItem = -1;
  903.     Boolean done = false;
  904.     Point tp;
  905.     GDHandle saveGD;
  906.     Str255 text;
  907.     long num;
  908.     long whichStage = gNumberSteps / 2;
  909.  
  910.  
  911.     if ((theDialog = GetNewDialog(PV_DLOG, nil, (WindowPtr) - 1)) == nil)
  912.         return;
  913.  
  914.     GetMouse(&tp);
  915.     GetGWorld(&savePort, &saveGD);
  916.     SetPort(theDialog);
  917.     GetDItem(theDialog, IT_OK, &itemType, &itemHdl, &itemRect);
  918.     PenSize(3, 3);
  919.     InsetRect(&itemRect, -4, -4);
  920.     FrameRoundRect(&itemRect, 16, 16);
  921.  
  922.  
  923.     GetDItem(theDialog, IT_STAGE, &itemType, &itemHdl, &itemRect);
  924.  
  925.     sprintf((char*)text, "%ld", whichStage);
  926.     c2pstr((char*)text);
  927.     SetIText(itemHdl, text);
  928.  
  929.     SelIText(theDialog, IT_STAGE, 0, 32767);
  930.  
  931.     while (!done)
  932.     {
  933.         ModalDialog(nil, &itemHit);
  934.         if (itemHit != lastItem)
  935.         {
  936.             switch (lastItem)
  937.             {
  938.                 case IT_STAGE:
  939.                     GetDItem(theDialog, IT_STAGE, &itemType, &itemHdl, &itemRect);
  940.                     GetIText(itemHdl, text);
  941.                     p2cstr(text);
  942.                     if (sscanf((char*)text, "%ld", &num) == 1 && num > 0 && num <= gNumberSteps)
  943.                         whichStage = num;
  944.                     else
  945.                         SysBeep(1);
  946.                     sprintf((char*)text, "%ld", whichStage);
  947.                     c2pstr((char*)text);
  948.                     SetIText(itemHdl, text);
  949.                     break;
  950.             }
  951.             lastItem = itemHit;
  952.         }
  953.         switch (itemHit)
  954.         {
  955.             case IT_OK:
  956.                 done = true;
  957.                 break;
  958.             case IT_CANCEL:
  959.                 whichStage = 0;
  960.                 done = true;
  961.                 break;
  962.             default:
  963.                 break;
  964.         }
  965.     }
  966.     CloseDialog(theDialog);
  967.  
  968.     if (whichStage)
  969.     {
  970.  
  971.         Rect rect;
  972.  
  973.         sprintf((char*)text, "Preview %d of %d", whichStage, gNumberSteps);
  974.         c2pstr((char*)text);
  975.  
  976.         rect = gSrcWindow->portRect;
  977.         SetGWorld(gSrcWindow, nil);
  978.         LocalToGlobal((Point *) & rect.top);
  979.         LocalToGlobal((Point *) & rect.bottom);
  980.         OffsetRect(&rect, 20, 20);
  981.         if (gOversample)
  982.         {
  983.             rect.right = rect.left + (rect.right - rect.left) / 2;
  984.             rect.bottom = rect.top + (rect.bottom - rect.top) / 2;
  985.         }
  986.         SetGWorld(savePort, saveGD);
  987.         if (gDstWindow)
  988.         {
  989.             CloseWindow((WindowPtr)gDstWindow);
  990.             gDstWindow = nil;
  991.         }
  992.         if ((gDstWindow = (CWindowPtr)NewCWindow(nil, &rect, text, true, zoomDocProc, (WindowPtr) - 1, true, 0)) == nil)
  993.         {
  994.             Error("NewCWindow Failed", 0);
  995.             goto done;
  996.         }
  997.         BringToFront((WindowPtr)gDstWindow);
  998.         HiliteWindow((WindowPtr)gDstWindow, true);
  999.         SetGWorld((CGrafPtr)gDstWorld, nil);
  1000.         PaintRect(&gDstWorld->portRect);
  1001.  
  1002.  
  1003.         if (gDstWorld && gWorld && gAltWorld)
  1004.             DoStage(whichStage, gNumberSteps, gBackwards);
  1005.  
  1006.         SetGWorld((CGrafPtr)gDstWindow, nil);
  1007.         CopyBits((BitMap *) * gDstWorld->portPixMap, (BitMap *) * gDstWindow->portPixMap, &gDstWorld->portRect, &gDstWindow->portRect, ditherCopy, nil);
  1008.     }
  1009. done:SetGWorld(savePort, saveGD);
  1010. }
  1011.  
  1012.  
  1013. /*********************************************
  1014.   Create the movie by processing all the frames.
  1015. ********************************************/
  1016.  
  1017.  
  1018. void DoMovie(void)
  1019.  
  1020. {
  1021.     GWorldPtr saveWorld;
  1022.     GDHandle saveGD;
  1023.     short resRefNum;
  1024.     OSErr result;
  1025.     Rect rect;
  1026.  
  1027.     /* Stuff for creating the file */
  1028.  
  1029.     Point dlgPos =
  1030.     {
  1031.         100,  100
  1032.     }
  1033.     ;                                            /* Position the dialog box */
  1034.     SFReply sfr;                                /* StdFile reply */
  1035.     FSSpec mySpec;                                /* Data structure with filename, etc. */
  1036.     Movie gMovie = 0;                            /* Our movie, track and media */
  1037.     Track gTrack;
  1038.     Media gMedia;
  1039.     long maxCompressedFrameSize;                /* Max size of compressed frame        */
  1040.     long compressedFrameSize;                    /* Size of current compressed frame */
  1041.     Handle compressedFrameBitsH = nil;            /* Buffer for the compressed data    */
  1042.     ImageDescription * *imageDescriptionH = nil;/* Contains info about the sample    */
  1043.     Ptr data;
  1044.     EventRecord myEvent;
  1045.     ImageSequence seq;
  1046.     static Str255 name = "\pMy Movie";
  1047.     Rect dstRect;
  1048.     short width,
  1049.      height;
  1050.     TimeValue timeVal;
  1051.  
  1052.  
  1053.  
  1054.     if (gDstWindow)
  1055.     {
  1056.         CloseWindow((WindowPtr)gDstWindow);
  1057.         gDstWindow = nil;
  1058.     }
  1059.  
  1060.     /* Prompt the user for a file name and create it */
  1061.  
  1062.     SFPutFile(dlgPos, (StringPtr)"\pMovie file to create:", (StringPtr)name, nil, &sfr);
  1063.     if (!sfr.good)
  1064.         return;
  1065.     BlockMove(sfr.fName, name, sfr.fName[0] + 1);
  1066.     GetGWorld(&saveWorld, &saveGD);
  1067.  
  1068.  
  1069.  
  1070.     width = gRect.right - gRect.left;
  1071.     height = gRect.bottom - gRect.top;
  1072.     if (gOversample)
  1073.     {
  1074.         width /= 2;
  1075.         height /= 2;
  1076.     }
  1077.     SetRect(&rect, 80, 80, width + 80, height + 80);
  1078.     if ((gDstWindow = (CWindowPtr)NewCWindow(nil, &rect, sfr.fName, true, zoomDocProc, (WindowPtr) - 1, true, 0)) == nil)
  1079.     {
  1080.         Error("NewCWindow Failed", 0);
  1081.         goto done;
  1082.     }
  1083.     BringToFront((WindowPtr)gDstWindow);
  1084.     HiliteWindow((WindowPtr)gDstWindow, true);
  1085.  
  1086.     imageDescriptionH = (ImageDescription * *)NewHandle(sizeof(ImageDescription));/* handle for image descriptor */
  1087.     if (imageDescriptionH == nil)
  1088.     {
  1089.         Error("Out of Memory", MemError());
  1090.         goto done;
  1091.     }
  1092.  
  1093.     ClearMoviesStickyError();                    /* Clear any old errors */
  1094.     result = FSMakeFSSpec(sfr.vRefNum, 0, (unsigned char*)sfr.fName, &mySpec);
  1095.     if (result == fnfErr)
  1096.         result = 0;
  1097.     CreateMovieFile(&mySpec, 'TVOD', 0, createMovieFileDeleteCurFile, &resRefNum, &gMovie);
  1098.  
  1099.     gTrack = NewMovieTrack(gMovie, (long)width << 16, (long)height << 16, 0);
  1100.     gMedia = NewTrackMedia(gTrack, VideoMediaType, gFrameRate, nil, (OSType)nil);
  1101.     BeginMediaEdits(gMedia);                    /* We do this since we are adding samples to the media */
  1102.     GetMaxCompressionSize(gAltWorld->portPixMap, &gAltWorld->portRect, gCodecDepth, gCodecQuality, gCodecType, gCodecID, &maxCompressedFrameSize);
  1103.  
  1104.     compressedFrameBitsH = NewHandle(maxCompressedFrameSize);
  1105.     if (compressedFrameBitsH == nil)
  1106.     {
  1107.         EndMediaEdits(gMedia);
  1108.         Error("Out of Memory", MemError());
  1109.         goto bail;
  1110.     }
  1111.     GetGWorld(&saveWorld, &saveGD);
  1112.     SetGWorld((CGrafPtr)gDstWorld, nil);
  1113.     PaintRect(&gDstWorld->portRect);
  1114.  
  1115.     if ((result = CompressSequenceBegin(&seq, gDstWorld->portPixMap, nil, &gDstWorld->portRect, nil, gCodecDepth, gCodecType, gCodecID, gCodecQuality, gCodecTemporalQuality, gKeyFrameRate, nil, codecFlagUpdatePreviousComp, imageDescriptionH)) != 0)
  1116.     {
  1117.         Error("CompressSequenceBegin Failed", result);
  1118.         goto bail2;
  1119.     }
  1120.     SetGWorld(saveWorld, saveGD);
  1121.     while (WaitNextEvent(everyEvent, &myEvent, 0, nil) != 0)
  1122.     {
  1123.         if (HandleEvents(&myEvent))
  1124.         {
  1125.             CDSequenceEnd(seq);
  1126.             EndMediaEdits(gMedia);
  1127.             return;
  1128.         }
  1129.     }
  1130.     SetRect(&dstRect, 0, 0, gRect.right / 2, gRect.bottom / 2);
  1131.     for (gFrameNumber = 0; gFrameNumber <= gNumberSteps; gFrameNumber++)
  1132.     {
  1133.         SetGWorld(saveWorld, saveGD);
  1134.         if (WaitNextEvent(everyEvent, &myEvent, 0, nil) != 0)
  1135.         {
  1136.             if (HandleEvents(&myEvent))
  1137.             {
  1138.                 break;
  1139.             }
  1140.         }
  1141.         SetGWorld((CGrafPtr)gDstWorld, nil);
  1142.         PaintRect(&gDstWorld->portRect);
  1143.  
  1144.         if (gDstWorld && gWorld && gAltWorld)
  1145.             DoStage(gFrameNumber, gNumberSteps, gBackwards);
  1146.  
  1147.         SetGWorld((CGrafPtr)gDstWindow, nil);
  1148.         InvalRect(&gDstWindow->portRect);
  1149.         DoHLock(compressedFrameBitsH);
  1150.         data = StripAddress(*compressedFrameBitsH);
  1151.         if (gOversample)
  1152.         {
  1153.             SetGWorld(gBufferWorld, nil);
  1154.             CopyBits((BitMap *) * gDstWorld->portPixMap, (BitMap *) * gBufferWorld->portPixMap, &gDstWorld->portRect, &dstRect, ditherCopy, nil);
  1155.  
  1156.             result = CompressSequenceFrame(seq, gBufferWorld->portPixMap, &dstRect, codecFlagUpdatePreviousComp, data, &compressedFrameSize, nil, nil);
  1157.         }
  1158.         else
  1159.         {
  1160.             SetGWorld((CGrafPtr)gDstWorld, nil);
  1161.             result = CompressSequenceFrame(seq, gDstWorld->portPixMap, &gDstWorld->portRect, codecFlagUpdatePreviousComp, data, &compressedFrameSize, nil, nil);
  1162.         }
  1163.         if (result)
  1164.         {
  1165.             Error("Compress Sequence Frame Failed", result);
  1166.             break;
  1167.         }
  1168.         DoHUnlock(compressedFrameBitsH);
  1169.         result = AddMediaSample(gMedia, compressedFrameBitsH, 0L, compressedFrameSize, (TimeValue)1, (SampleDescriptionHandle)imageDescriptionH, 1L, 0, nil);
  1170.         if (result)
  1171.         {
  1172.             Error("AddMediaSample Failed", result);
  1173.             break;
  1174.         }
  1175.     }
  1176. bail2:CDSequenceEnd(seq);
  1177. bail:EndMediaEdits(gMedia);                        /* We're done adding samples */
  1178.     timeVal = GetMediaDuration(gMedia);
  1179.     result = InsertMediaIntoTrack(gTrack, 0L, 0L, timeVal, 1L << 16);
  1180.     if (result)
  1181.     {
  1182.         Error("InsertMediaIntoTrack Failed", result);
  1183.     }
  1184.     result = AddMovieResource(gMovie, resRefNum, nil, nil);
  1185.     if (result)
  1186.     {
  1187.         Error("AddMovieResource Failed", result);
  1188.     }
  1189.     CloseMovieFile(resRefNum);
  1190.  
  1191. done:SetGWorld(saveWorld, saveGD);
  1192.     if (imageDescriptionH)
  1193.         DoDisposHandle((Handle)imageDescriptionH);
  1194.     if (compressedFrameBitsH)
  1195.         DoDisposHandle((Handle)compressedFrameBitsH);
  1196.     if (gMovie)
  1197.         DisposeMovie(gMovie);
  1198.     if (gDstWindow)
  1199.     {
  1200.         CloseWindow((WindowPtr)gDstWindow);
  1201.         gDstWindow = nil;
  1202.     }
  1203.     SetGWorld(saveWorld, saveGD);
  1204. }
  1205.  
  1206.  
  1207.  
  1208. /*********************************************
  1209.   Stubs
  1210. ********************************************/
  1211.  
  1212. void DoCopy(void)
  1213. {
  1214.  
  1215. }
  1216.  
  1217.  
  1218. void DoCut(void)
  1219. {
  1220. }
  1221.  
  1222.  
  1223. void DoPaste(void)
  1224. {
  1225.  
  1226. }
  1227.  
  1228.  
  1229. void DoClear(void)
  1230. {
  1231.  
  1232.  
  1233. }
  1234.  
  1235.  
  1236. void DoUndo(void)
  1237. {
  1238.  
  1239.  
  1240. }
  1241.  
  1242.  
  1243.  
  1244. /*********************************************
  1245.   Process menu command.
  1246. ********************************************/
  1247.  
  1248. short DoCommand(long mResult)
  1249. {
  1250.     short theMenu,
  1251.      theItem;
  1252.     Str255 daName;
  1253.     GDHandle saveGD;
  1254.     CGrafPtr savePort;
  1255.     OSErr res = 0;
  1256.  
  1257. #define HIshort(aLong)        (((aLong) >> 16) & 0xFFFF)
  1258. #define LOshort(aLong)        ((aLong) & 0xFFFF)
  1259.  
  1260.     theItem = LOshort(mResult);
  1261.     theMenu = HIshort(mResult);                    /* This is the resource ID */
  1262.  
  1263.  
  1264.     switch (theMenu)
  1265.     {
  1266.         case APPLE_MENU_ID:
  1267.             if (theItem == 1)
  1268.             {
  1269.                 ShowAboutBox();
  1270.             }
  1271.             else
  1272.             {
  1273.                 GetItem(gMenus[0], theItem, daName);
  1274.                 GetGWorld(&savePort, &saveGD);
  1275.                 (void)OpenDeskAcc(daName);
  1276.                 SetGWorld(savePort, saveGD);
  1277.             }
  1278.             break;
  1279.  
  1280.         case FILE_MENU_ID:
  1281.             {
  1282.  
  1283.                 switch (theItem)
  1284.                 {
  1285.                     case FILE_M_OPEN:
  1286.                         DoOpen(nil);
  1287.                         FixMenus();
  1288.                         break;
  1289.                     case FILE_M_CLOSE:
  1290.                         DoClose(gActiveWindow);
  1291.                         FixMenus();
  1292.                         res = 1;
  1293.                         break;
  1294.                     case FILE_M_SAVE:
  1295.                         FixMenus();
  1296.                         break;
  1297.                     case FILE_M_QUIT:
  1298.                         {
  1299.                             Boolean abortion = false;
  1300.                             while (gActiveWindow)
  1301.                             {
  1302.                                 if (DoClose(gActiveWindow) < 0)
  1303.                                 {
  1304.                                     abortion = true;
  1305.                                     break;
  1306.                                 }
  1307.                             }
  1308.                             if (!abortion)
  1309.                                 gExitFlag = true;/* Request exit */
  1310.                             res = 1;
  1311.                             break;
  1312.                         }
  1313.                 }
  1314.             }
  1315.             break;
  1316.         case EDIT_MENU_ID:
  1317.             if (!SystemEdit(theItem - 1))
  1318.             {
  1319.                 switch (theItem)
  1320.                 {
  1321.                     case EDIT_M_UNDO:
  1322.                         DoUndo();
  1323.                         break;
  1324.                     case EDIT_M_CUT:
  1325.                         DoCut();
  1326.                         break;
  1327.                     case EDIT_M_COPY:
  1328.                         DoCopy();
  1329.                         break;
  1330.                     case EDIT_M_PASTE:
  1331.                         DoPaste();
  1332.                         break;
  1333.                     case EDIT_M_CLEAR:
  1334.                         DoClear();
  1335.                         break;
  1336.                 }
  1337.             }
  1338.             FixMenus();
  1339.             break;
  1340.  
  1341.         case MOVIE_MENU_ID:
  1342.  
  1343.             switch (theItem)
  1344.             {
  1345.                 case MOVIE_M_COMPRESS:
  1346.                     SetCompression();
  1347.                     break;
  1348.                 case MOVIE_M_STAGES:
  1349.                     DoClose((WindowPtr)gDstWindow);
  1350.                     SetStages();
  1351.                     break;
  1352.                 case MOVIE_M_OVERSAMPLE:
  1353.                     gOversample =!gOversample;
  1354.                     CheckItem(gMenus[MOVIE_MENU], theItem, gOversample);
  1355.                     break;
  1356.                 case MOVIE_M_BACKWARDS:
  1357.                     DoClose((WindowPtr)gDstWindow);
  1358.                     gBackwards =!gBackwards;
  1359.                     CheckItem(gMenus[MOVIE_MENU], theItem, gBackwards);
  1360.                     break;
  1361.                 case MOVIE_M_PREVIEW:
  1362.                     DoPreview();
  1363.                     break;
  1364.                 case MOVIE_M_MOVIE:
  1365.                     DoMovie();
  1366.                     break;
  1367.             }
  1368.             break;
  1369.  
  1370.         default:
  1371.             break;
  1372.  
  1373.     }                                            /*endsw theMenu*/
  1374.  
  1375.     HiliteMenu(0);
  1376.     return (res);
  1377. }
  1378.  
  1379.  
  1380.  
  1381. /********************************************
  1382.   Process events.
  1383. ********************************************/
  1384.  
  1385. Boolean HandleEvents(EventRecord* myEvent)
  1386. {
  1387.     Rect dragRect;
  1388.     WindowPtr whichWindow;
  1389.     short res = 0;
  1390.     GWorldPtr saveWorld;
  1391.     GDHandle saveGD;
  1392.  
  1393.     GetGWorld(&saveWorld, &saveGD);
  1394.  
  1395.     switch (myEvent->what)
  1396.     {
  1397.         case mouseDown:
  1398.             switch ((short)FindWindow(myEvent->where, &whichWindow))
  1399.             {
  1400.                 case inSysWindow:
  1401.                     SystemClick(myEvent, whichWindow);
  1402.                     break;
  1403.  
  1404.                 case inMenuBar:
  1405.                     res = DoCommand(MenuSelect(myEvent->where));
  1406.                     break;
  1407.  
  1408.                 case inDrag:
  1409.                     SetPort((GrafPtr)whichWindow);
  1410.                     SetRect(&dragRect, 4, 20 + 4, qd.screenBits.bounds.right - 4, qd.screenBits.bounds.bottom - 4);
  1411.                     DragWindow(whichWindow, myEvent->where, &dragRect);
  1412.                     break;
  1413.  
  1414.                 case inGrow:
  1415.                     break;
  1416.  
  1417.                 case inGoAway:
  1418.                     if (TrackGoAway(whichWindow, myEvent->where))
  1419.                     {
  1420.                         DoClose(whichWindow);
  1421.                         res = true;
  1422.                     }
  1423.                     break;
  1424.  
  1425.                 case inZoomIn:
  1426.                     break;
  1427.  
  1428.                 case inZoomOut:
  1429.                     break;
  1430.  
  1431.                 case inContent:
  1432.  
  1433.                     if (whichWindow != FrontWindow())
  1434.                     {
  1435.                         SelectWindow(whichWindow);
  1436.                         gActiveWindow = whichWindow;
  1437.                     }
  1438.                     FixMenus();
  1439.                     break;
  1440.  
  1441.                 default:
  1442.                     break;
  1443.             }
  1444.             break;
  1445.  
  1446.         case keyDown:
  1447.             if (((myEvent->modifiers & cmdKey) != 0))
  1448.             {
  1449.                 res = DoCommand(MenuKey(myEvent->message & charCodeMask));
  1450.             }
  1451.             break;
  1452.  
  1453.         case updateEvt:
  1454.  
  1455.             DoUpdate((CWindowPtr)myEvent->message);
  1456.             break;
  1457.  
  1458.         case activateEvt:
  1459.             whichWindow = (WindowPtr)myEvent->message;
  1460.             if ((myEvent->modifiers & activeFlag))
  1461.             {
  1462.                 gActiveWindow = whichWindow;
  1463.             }
  1464.             break;
  1465.  
  1466.         default:
  1467.             break;
  1468.  
  1469.     }
  1470.     SetGWorld(saveWorld, saveGD);
  1471.     return (res);
  1472. }
  1473.  
  1474.  
  1475.  
  1476. /********************************************
  1477.   Allocate the image buffers for the processing
  1478. ********************************************/
  1479.  
  1480. OSErr AllocateBuffers(void)
  1481. {
  1482.  
  1483.     Rect rect = gRect;
  1484.     OSErr result = 0;
  1485.     short depth = gDepth > 32 ? (gDepth - 32) : gDepth;
  1486.     CTabHandle clut = nil;
  1487.  
  1488.     OffsetRect(&rect, -rect.left, -rect.top);
  1489.  
  1490.     if (gDepth > 32)
  1491.         clut = GetCTable(gDepth);
  1492.  
  1493.     if (gDstWorld)
  1494.     {
  1495.         DisposeGWorld(gDstWorld);
  1496.         gDstWorld = nil;
  1497.     }
  1498.     if (gBufferWorld)
  1499.     {
  1500.         DisposeGWorld(gBufferWorld);
  1501.         gBufferWorld = nil;
  1502.     }
  1503.     if ((result = NewGWorld(&gWorld, depth, &rect, clut, nil, 0)) != 0)
  1504.     {
  1505.         if ((result = NewGWorld(&gWorld, depth, &rect, clut, nil, useTempMem)) != 0)
  1506.         {
  1507.             Error("NewGWorld Failed", result);
  1508.             goto done;
  1509.         }
  1510.     }
  1511.     if ((result = NewGWorld(&gAltWorld, depth, &rect, clut, nil, 0)) != 0)
  1512.     {
  1513.         if ((result = NewGWorld(&gAltWorld, depth, &rect, clut, nil, useTempMem)) != 0)
  1514.         {
  1515.             Error("NewGWorld Failed", result);
  1516.             goto done;
  1517.         }
  1518.     }
  1519.     if ((result = NewGWorld(&gBufferWorld, depth, &rect, clut, nil, 0)) != 0)
  1520.     {
  1521.         if ((result = NewGWorld(&gBufferWorld, depth, &rect, clut, nil, useTempMem)) != 0)
  1522.         {
  1523.             Error("NewGWorld Failed", result);
  1524.             goto done;
  1525.         }
  1526.     }
  1527.     if ((result = NewGWorld(&gDstWorld, depth, &rect, clut, nil, 0)) != 0)
  1528.     {
  1529.         if ((result = NewGWorld(&gDstWorld, depth, &rect, clut, nil, useTempMem)) != 0)
  1530.         {
  1531.             Error("NewGWorld Failed", result);
  1532.             goto done;
  1533.         }
  1534.     }
  1535. done:if (result)
  1536.     {
  1537.         if (gWorld)
  1538.             DisposeGWorld(gWorld);
  1539.         gWorld = nil;
  1540.         if (gAltWorld)
  1541.             DisposeGWorld(gAltWorld);
  1542.         gAltWorld = nil;
  1543.         if (gDstWorld)
  1544.             DisposeGWorld(gDstWorld);
  1545.         gDstWorld = nil;
  1546.         if (gBufferWorld)
  1547.             DisposeGWorld(gBufferWorld);
  1548.         gBufferWorld = nil;
  1549.  
  1550.     }
  1551.     if (clut)
  1552.         DisposeCTable(clut);
  1553.     return (result);
  1554. }
  1555.  
  1556.  
  1557.  
  1558. /********************************************
  1559.   Make a source window 
  1560. ********************************************/
  1561.  
  1562. CWindowPtr MakeSWindow(Rect* frame,
  1563.                        StringPtr name,
  1564.                        GWorldPtr buffer)
  1565. {
  1566.     CWindowPtr wind;
  1567.  
  1568.     if ((wind = (CWindowPtr)NewCWindow(nil, frame, name, false, zoomDocProc, (WindowPtr) - 1, true, 0)) == nil)
  1569.     {
  1570.         Error("NewCWindow Failed", 0);
  1571.         return (nil);
  1572.     }
  1573.     ShowWindow((WindowPtr)wind);
  1574.     BringToFront((WindowPtr)wind);
  1575.     HiliteWindow((WindowPtr)wind, true);
  1576.     SetWRefCon((WindowPtr)wind, (long)buffer);
  1577.     return (wind);
  1578. }
  1579.  
  1580.  
  1581.  
  1582.  
  1583. /********************************************
  1584.   Open a file.
  1585. ********************************************/
  1586.  
  1587. OSErr DoOpen(FSSpec* fsp)
  1588. {
  1589.     long result = noErr;
  1590.     Rect zpFrame;
  1591.     GWorldPtr saveWorld;
  1592.     GDHandle saveGD;
  1593.     short oFile = -1;
  1594.     StandardFileReply theSFR;
  1595.  
  1596.  
  1597.     GetGWorld(&saveWorld, &saveGD);
  1598.     if (fsp == nil)
  1599.     {
  1600.         SFTypeList types =
  1601.         {
  1602.             'PICT',  0
  1603.         }
  1604.         ;
  1605.  
  1606.         if (gHasNewStdFile)
  1607.             StandardGetFile(nil, 1, types, &theSFR);
  1608.         else
  1609.         {
  1610.             SFReply osfr;
  1611.             Point pt =
  1612.             {
  1613.                 100,  100
  1614.             }
  1615.             ;
  1616.  
  1617.             SFGetFile(pt, (ConstStr255Param)"", nil, 1, types, nil, &osfr);
  1618.             theSFR.sfGood = osfr.good;
  1619.             theSFR.sfReplacing = osfr.copy;
  1620.             theSFR.sfType = osfr.fType;
  1621.             if (osfr.good)
  1622.                 FSMakeFSSpec(osfr.vRefNum, 0L, osfr.fName, &theSFR.sfFile);
  1623.         }
  1624.         if (!theSFR.sfGood)
  1625.         {
  1626.             return (1);
  1627.         }
  1628.     }
  1629.     else
  1630.     {
  1631.         theSFR.sfFile = *fsp;
  1632.     }
  1633.  
  1634.     if (FSpOpenDF(&theSFR.sfFile, fsRdPerm, &oFile))
  1635.     {
  1636.         result = -1;
  1637.         goto done;
  1638.     }
  1639.  
  1640.  
  1641.     /************************************************
  1642.      *
  1643.      *    Get the picture frame, to see how big of a window to make.
  1644.      *
  1645.     ************************************************/
  1646.  
  1647.     if (GetPictureFileHeader(oFile, &gOriginalPicFrame, nil))
  1648.     {
  1649.         result = -1;
  1650.         goto done;
  1651.     }
  1652.  
  1653.     if (gSrcWindow == nil)
  1654.     {
  1655.  
  1656.         OffsetRect(&gOriginalPicFrame, -gOriginalPicFrame.left, -gOriginalPicFrame.top);
  1657.         if (gOversample)
  1658.         {
  1659.             gOriginalPicFrame.right *= 2;
  1660.             gOriginalPicFrame.bottom *= 2;
  1661.         }
  1662.         gRect = gOriginalPicFrame;
  1663.         zpFrame = gRect;
  1664.  
  1665.         if ((result = AllocateBuffers()) != 0)
  1666.             goto done;
  1667.         OffsetRect(&zpFrame, 50, 50);
  1668.         gSrcWindow = MakeSWindow(&zpFrame, theSFR.sfFile.name, gWorld);
  1669.         SetGWorld((CGrafPtr)gWorld, nil);
  1670.         if ((result = DrawPictureFile(oFile, &gWorld->portRect, nil)) != 0)
  1671.         {
  1672.             Error("DrawPictureFile Failed", result);
  1673.             goto done;
  1674.         }
  1675.     }
  1676.     else
  1677.     {
  1678.  
  1679.         zpFrame = gRect;
  1680.         OffsetRect(&zpFrame, 70, 70);
  1681.         gAltWindow = MakeSWindow(&zpFrame, theSFR.sfFile.name, gAltWorld);
  1682.         SetGWorld((CGrafPtr)gAltWorld, nil);
  1683.         if ((result = DrawPictureFile(oFile, &gAltWorld->portRect, nil)) != 0)
  1684.         {
  1685.             Error("DrawPictureFile Failed", result);
  1686.             goto done;
  1687.         }
  1688.     }
  1689. done:if (oFile != -1)
  1690.         FSClose(oFile);
  1691.     SetGWorld(saveWorld, saveGD);
  1692.     return (result);
  1693.  
  1694. }
  1695.  
  1696.  
  1697. /********************************************
  1698.   Update a window
  1699. ********************************************/
  1700.  
  1701. void DoUpdate(CWindowPtr wind)
  1702.  
  1703. {
  1704.  
  1705.     GWorldPtr saveWorld,  gw;
  1706.     GDHandle saveGD;
  1707.     RGBColor gray =
  1708.     {
  1709.         0xc000,  0xc000, 0xc000
  1710.     }
  1711.     ;
  1712.     char c[32];
  1713.  
  1714.     GetGWorld(&saveWorld, &saveGD);
  1715.     if (wind == gDstWindow)
  1716.     {
  1717.         BeginUpdate((WindowPtr)wind);
  1718.         SetGWorld((CGrafPtr)wind, nil);
  1719.         CopyBits((BitMap *) * gDstWorld->portPixMap, (BitMap *) * wind->portPixMap, &gDstWorld->portRect, &wind->portRect, ditherCopy, nil);
  1720.         if (gFrameNumber >= 0)
  1721.         {
  1722.             MoveTo(20, 20);
  1723.             TextSize(12);
  1724.             TextFace(bold);
  1725.             TextMode(patBic);
  1726.             NumToString(gFrameNumber + 1, (StringPtr) & c);
  1727.             DrawString((StringPtr) & c);
  1728.             DrawString((StringPtr)"\p/");
  1729.             NumToString(gNumberSteps + 1, (StringPtr) & c);
  1730.             DrawString((StringPtr) & c);
  1731.             MoveTo(21, 21);
  1732.             TextMode(srcOr);
  1733.             NumToString(gFrameNumber + 1, (StringPtr) & c);
  1734.             DrawString((StringPtr) & c);
  1735.             DrawString((StringPtr)"\p/");
  1736.             NumToString(gNumberSteps + 1, (StringPtr) & c);
  1737.             DrawString((StringPtr) & c);
  1738.         }
  1739.         EndUpdate((WindowPtr)wind);
  1740.         SetGWorld(saveWorld, saveGD);
  1741.         return;
  1742.     }
  1743.     SetGWorld(wind, nil);
  1744.     gw = (GWorldPtr)GetWRefCon((WindowPtr)wind);
  1745.     BeginUpdate((WindowPtr)wind);
  1746.     CopyBits((BitMap *) * gw->portPixMap, (BitMap *) * wind->portPixMap, &gw->portRect, &wind->portRect, ditherCopy, nil);
  1747.     EndUpdate((WindowPtr)wind);
  1748.     SetGWorld(saveWorld, saveGD);
  1749. }
  1750.  
  1751.  
  1752.  
  1753. /********************************************
  1754.   The main program
  1755. ********************************************/
  1756.  
  1757. void main(void)
  1758. {
  1759.  
  1760.     EventRecord myEvent;
  1761.  
  1762.     Initialize();
  1763.     EnterMovies();
  1764.  
  1765.  
  1766.     if (!gDoCrossFade)
  1767.     {
  1768.         gDepth = 40;                            // randomdotstereogram needs grayscale buffers
  1769.         gCodecType = 'smc ';                        // graphics compressor is good choice
  1770.         gCodecDepth = gDepth;                    // prime depth for std compression
  1771.         gRequiresAlternate = false;                // only needs one pict to do processing
  1772.     }
  1773.     else
  1774.     {
  1775.         gDepth = 32;                            // full resolution for best effect
  1776.         gRequiresAlternate = true;                // needs two picts to do processing
  1777.     }
  1778.     while (!gExitFlag)
  1779.     {
  1780.         if (WaitNextEvent(everyEvent, &myEvent, 1, nil) != 0)
  1781.         {
  1782.             HandleEvents(&myEvent);
  1783.         }
  1784.     }
  1785.  
  1786. done:ExitMovies();
  1787.     ExitToShell();
  1788. }
  1789.  
  1790.  
  1791.